<?php
declare (strict_types=1);

namespace app\command\pan;

use think\console\Command;
use think\console\Input;
use think\console\input\Option;
use think\console\Output;
use think\facade\Db;

class Table extends Command
{
    protected function configure()
    {
        // 指令配置
        $this->setName('table')
            ->addOption('table', null, Option::VALUE_REQUIRED, '表的名字')
            ->addOption('option', null, Option::VALUE_REQUIRED, 'controller|model|traits|json')
            ->addOption('f', null, Option::VALUE_REQUIRED, '强制覆盖')
            ->setDescription('一次性生成');
    }

    protected function execute(Input $input, Output $output)
    {

        // 指令输出
        if (!$input->hasOption('table')) {
            throw new \Exception('请输入--table 表的名字');
        }
        $sql = "select REFERENCED_TABLE_NAME as name, COLUMN_NAME as f_id , REFERENCED_COLUMN_NAME as id  from information_schema.KEY_COLUMN_USAGE where  POSITION_IN_UNIQUE_CONSTRAINT ='1' and  table_name='" . config('database.connections.mysql.prefix') . $input->getOption('table') . "' and TABLE_SCHEMA ='" . config('database.connections.mysql.database') . "'";
        $table_f = Db::query($sql);
        foreach ($table_f as $k => $v) {
            $table_f[$k]['name'] = str_replace(config('database.connections.mysql.prefix'), '', $v['name']);
            $table_f[$k]['uc_name'] = all_ucwords(str_replace(config('database.connections.mysql.prefix'), '', $v['name']));
            $table_f[$k]['all_name'] =str_replace('_','',config('database.connections.mysql.prefix').$table_f[$k]['uc_name']);
        }
        $table_f2=$table_f;
        $num=1;
        foreach ($table_f as $k => $v) {
            foreach ($table_f2 as $key => $value) {
                if($k!==$key){
                    if($v['all_name']==$value['all_name']){
                        $table_f[$k]['all_name']=$table_f[$k]['all_name'].$num;
                        $num++;
                        break;
                    }
                }
            }
        }

        //public
        $sql = "select column_name as name,column_comment as remark,data_type as type,is_nullable as is_null ,COLUMN_KEY as ckey from information_schema.columns where table_name='" . config('database.connections.mysql.prefix') . $input->getOption('table') . "' and TABLE_SCHEMA ='" . config('database.connections.mysql.database') . "'";
        $table_build = Db::query($sql);
        if (config('base.if_pk')) {
            foreach ($table_build as $v) {
                if ($v['ckey'] == 'PRI') {
                    $pk = $v['name'];
                }
            }
        } else {
            $pk = config('base.pk');
        }
        $trait_name = all_ucwords($input->getOption('table')).'Trait';
        $sql = "select table_comment as remark  from information_schema.TABLES where table_name='" . config('database.connections.mysql.prefix') . $input->getOption('table') . "' and TABLE_SCHEMA ='" . config('database.connections.mysql.database') . "'";
        $table_remark = Db::query($sql)[0]['remark'];
        $path=explode('_',$input->getOption('table'))[0];
        if($input->getOption('option')=='traits' || $input->hasOption('option')===false){
            //traits
            $namespace_table = config('base.model_namespace') . '\\' . all_ucwords($input->getOption('table'));
            $fieldRaw = implode(',', array_column($table_build, 'name'));
            $table_name = $input->getOption('table');
            $rules = '';
            $message = '';
            foreach ($table_build as $v) {
                if ($v['is_null'] == 'NO' && $v['ckey'] != 'PRI') {
                    $rules .= "\t\t\t" . "'" . $v['name'] . "'=>'require'," . PHP_EOL;
                    if ($v['type'] == 'enum' || $v['type'] == 'set') {
                        $value = config('base.select_msg');
                    } else {
                        $value = config('base.msg');
                    }
                    $value = str_replace('{$remark}', $v['remark'], $value);
                    $message .= "\t\t\t" . "'" . $v['name'] . ".require'=>'" . $value . "'," . PHP_EOL;
                }
                if ($v['ckey'] == 'UNI') {
                    $rules .= "\t\t\t" . "'" . $v['name'] . "'=>'unique:" . $input->getOption('table') . "'," . PHP_EOL;
                    $value = config('base.unique_msg');
                    $value = str_replace('{$remark}', $v['remark'], $value);
                    $message .= "\t\t\t" . "'" . $v['name'] . ".unique'=>'" . $value . "'," . PHP_EOL;
                }
            }
            $join = '';
            $uc_table = all_ucwords($input->getOption('table'));
            foreach ($table_f as $v) {
                $sql = "select column_name as name,column_comment as remark,data_type as type,is_nullable as is_null ,COLUMN_KEY as ckey from information_schema.columns where table_name='" . config('database.connections.mysql.prefix') . $v['name'] . "' and TABLE_SCHEMA ='" . config('database.connections.mysql.database') . "'";
                $d = Db::query($sql);
                $arr=array_column($d, 'name');
                foreach ($arr as $key=>$value){
                    $arr[$key]="'".$value."'";
                }
                $d = implode(',', $arr);
                $join .= "\t\t\t" . "'" . $v['all_name'] . "'=>[" . $d . "]," . PHP_EOL;
            }
            $trait_file = file_get_contents(app()->getAppPath() . 'tem\\' . 'trait_tem.txt');
            $trait_file = str_replace('{$namespace_table}', $namespace_table, $trait_file);
            $trait_file = str_replace('{$trait_name}', $trait_name, $trait_file);
            $trait_file = str_replace('{$fieldRaw}', $fieldRaw, $trait_file);
            $trait_file = str_replace('{$table_name}', $table_name, $trait_file);
            $trait_file = str_replace('{$pk}', $pk, $trait_file);
            $trait_file = str_replace('{$rules}', $rules, $trait_file);
            $trait_file = str_replace('{$message}', $message, $trait_file);
            $trait_file = str_replace('{$uc_table}', $uc_table, $trait_file);
            $trait_file = str_replace('{$join}', $join, $trait_file);

            if(!file_exists(app()->getAppPath() . 'traits\\' . $trait_name . '.php') || $input->hasOption('f')===true){
                if(!is_dir(app()->getAppPath() . 'traits')){
                    mkdir(app()->getAppPath() . 'traits');
                }
                file_put_contents(app()->getAppPath() . 'traits\\' . $trait_name . '.php', $trait_file);
            }else{
                echo app()->getAppPath() . 'traits\\' . $trait_name . '.php'.'文件已存在'.PHP_EOL;
            }
        }

        if($input->getOption('option')=='model' || $input->hasOption('option')===false){
            //model
            $model_namespace=config('base.model_namespace');
            $model_class_name=all_ucwords($input->getOption('table'));
            $create_time=config('base.create_time');
            $update_time=config('base.update_time');
            $model_func='';
            $str='$this->hasOne';
            foreach ($table_f as $v) {
                $model_func.="\t" ."public function ".$v['all_name']."() {return ".$str." ('".$v['uc_name']."','".$v['id']."','".$v['f_id']."');}".PHP_EOL;
            }
            $model_file = file_get_contents(app()->getAppPath(). 'tem\\' . 'model_tem.txt');
            $model_file = str_replace('{$model_namespace}', $model_namespace, $model_file);
            $model_file = str_replace('{$model_class_name}', $model_class_name, $model_file);
            $model_file = str_replace('{$create_time}', $create_time, $model_file);
            $model_file = str_replace('{$update_time}', $update_time, $model_file);
            $model_file = str_replace('{$pk}', $pk, $model_file);
            $model_file = str_replace('{$model_func}', $model_func, $model_file);
            if(!file_exists(app()->getAppPath() . 'model\\' .config('base.model'). $model_class_name . '.php')|| $input->hasOption('f')===true){
                if(!is_dir(app()->getAppPath() . 'model\\' .config('base.model'))){
                    mkdir(app()->getAppPath() . 'model\\' .config('base.model'));
                }
                file_put_contents(app()->getAppPath() . 'model\\' .config('base.model'). $model_class_name . '.php', $model_file);
            }else{
                echo app()->getAppPath() . 'model\\' .config('base.model'). $model_class_name . '.php'.'文件已存在'.PHP_EOL;
            }
        }
        if($input->getOption('option')=='controller' || $input->hasOption('option')===false){
            //controller
            if(!is_dir(app()->getAppPath() .  'controller\\' .config('base.controller'))){
                mkdir(app()->getAppPath() .  'controller\\' .config('base.controller'));
            }
            if(!is_dir(app()->getRootPath().config('base.controller_name').'\\'.$path)){
                mkdir(app()->getRootPath().config('base.controller_name').'\\'.$path);
            }
            $controller_name=config('base.controller_name').'\\'.$path;
            $controller_class_name=all_ucwords($input->getOption('table'));
            $controller_file = file_get_contents(app()->getAppPath(). 'tem\\' . 'controller_tem.txt');
            $controller_file = str_replace('{$controller_name}', $controller_name, $controller_file);
            $controller_file = str_replace('{$trait_name}', $trait_name, $controller_file);
            $controller_file = str_replace('{$controller_class_name}', $controller_class_name, $controller_file);
            if(!file_exists(app()->getAppPath() . 'controller\\' .config('base.controller').$path.'\\'.$controller_class_name . '.php') || $input->hasOption('f')===true){
                file_put_contents(app()->getAppPath() . 'controller\\' .config('base.controller').$path.'\\'.$controller_class_name . '.php', $controller_file);
            }else{
                echo app()->getAppPath() . 'controller\\' .config('base.controller').$path.'\\'.$controller_class_name . '.php'.'文件已存在'.PHP_EOL;
            }
        }

        //json public
        $res_arr=Db::name($input->getOption('table'))->limit(1)->select()->toArray();
        if(!count($res_arr)){
            echo '表中无数据，只能生成路由'.PHP_EOL;
            $res='';
        }else{
            $res=$res_arr[0];
        }
        $url['index']=str_replace('\\','',config('base.controller')).'/'.$path.'/'.$input->getOption('table').'/'.'index';
        $dian['index']=str_replace('\\','',config('base.controller')).'.'.$path.'.'.$input->getOption('table').'/'.'index';
        $url['add']=str_replace('\\','',config('base.controller')).'/'.$path.'/'.$input->getOption('table').'/'.'add';
        $dian['add']=str_replace('\\','',config('base.controller')).'.'.$path.'.'.$input->getOption('table').'/'.'add';
        $url['edit']=str_replace('\\','',config('base.controller')).'/'.$path.'/'.$input->getOption('table').'/'.'edit';
        $dian['edit']=str_replace('\\','',config('base.controller')).'.'.$path.'.'.$input->getOption('table').'/'.'edit';
        $url['get_info']=str_replace('\\','',config('base.controller')).'/'.$path.'/'.$input->getOption('table').'/'.'get_info';
        $dian['get_info']=str_replace('\\','',config('base.controller')).'.'.$path.'.'.$input->getOption('table').'/'.'get_info';
        $url['del']=str_replace('\\','',config('base.controller')).'/'.$path.'/'.$input->getOption('table').'/'.'del';
        $dian['del']=str_replace('\\','',config('base.controller')).'.'.$path.'.'.$input->getOption('table').'/'.'del';
        if(!is_dir(app()->getAppPath() .'json')){
            mkdir(app()->getAppPath() .'json');
        }
        if($input->getOption('option')=='json' || !empty($res)){
            //json
            //index
            $arr=[];
            if(!empty($res)){
                foreach ($table_build as $v){
                    $value=[
                        "description"=>$v['remark'],
                        "is_checked"=> 1,
                        "key"=>"data.data.".$v['name'],
                        "type"=>"Text",
                        "field_type"=>"Object",
                        "value"=>$res[$v['name']]
                    ];
                    array_push($arr,$value);
                }
            }
            foreach ($table_f as $value){
                $res[$value['all_name']]=Db::name($value['name'])->select()[0];
                $sql = "select column_name as name,column_comment as remark,data_type as type,is_nullable as is_null ,COLUMN_KEY as ckey from information_schema.columns where table_name='" . config('database.connections.mysql.prefix') . $value['name'] . "' and TABLE_SCHEMA ='" . config('database.connections.mysql.database') . "'";
                $keys = Db::query($sql);
                $arr_f=[];
                foreach ($keys as $v){
                    $value2=[
                        "description"=>$v['remark'],
                        "is_checked"=> 1,
                        "key"=>"data.data.".$value['all_name'].'.'.$v['name'],
                        "type"=>"Text",
                        "field_type"=>"Object",
                        "value"=>$res[$value['all_name']][$v['name']]
                    ];
                    array_push($arr_f,$value2);
                }
                $arr=array_merge($arr,$arr_f);

            }
            $raw=addslashes(json_encode($res));
            $param=json_encode($arr);
            $param=str_replace('[','',$param);
            $param=str_replace(']','',$param);
            $json_index_file = file_get_contents(app()->getAppPath(). 'tem\\' . 'json_index_tem.txt');
            $json_index_file = str_replace('{$table_remark}', $table_remark, $json_index_file);
            $json_index_file = str_replace('{$url}', $url['index'], $json_index_file);
            $json_index_file = str_replace('{$test_api_url}',config('base.test_api_url'), $json_index_file);
            $json_index_file = str_replace('{$table_name}', $input->getOption('table'), $json_index_file);
            $json_index_file = str_replace('{$raw}', $raw, $json_index_file);
            $json_index_file = str_replace('{$param}', $param, $json_index_file);
            file_put_contents(app()->getAppPath() .'json\\'.str_replace('/','_',$url['index']).'.json', $json_index_file);
            //add
            $add_data='['.'\n'.'{'.'\n';
            $test_data='[{';
            foreach ($table_build as $value){
                if($pk!=$value['name']){
                    $add_data.=$value['name'].':'."\""."\",//".$value['remark'].'\n';
                    $test_data.='"'.$value['name'].'"'.':"'.$res[$value['name']].'",';
                }
            }
            $add_data.='}'.'\n'.']';
            $test_data.='}]';
            $test_chr=strrchr($test_data, ",");
            $test_data=str_replace($test_chr,ltrim($test_chr,','),$test_data);
            $test_data=rtrim($test_data, ",");
            $test_data=addslashes($test_data);
            $add_chr=strrchr($add_data, ",");
            $add_data=str_replace($add_chr,ltrim($add_chr,','),$add_data);
            $add_data=addslashes($add_data);
            $add_data=str_replace('\\\n','\n',$add_data);
            $json_add_file = file_get_contents(app()->getAppPath(). 'tem\\' . 'json_add_tem.txt');
            $json_add_file = str_replace('{$table_remark}', $table_remark, $json_add_file);
            $json_add_file = str_replace('{$url}', $url['add'], $json_add_file);
            $json_add_file = str_replace('{$test_data}', $test_data, $json_add_file);
            $json_add_file = str_replace('{$test_api_url}',config('base.test_api_url'), $json_add_file);
            $json_add_file = str_replace('{$add_data}',$add_data, $json_add_file);
            file_put_contents(app()->getAppPath() .'json\\'.str_replace('/','_',$url['add']).'.json', $json_add_file);
            //edit
            $edit_data='['.'\n'.'{'.'\n';
            $test_data='[{';
            foreach ($table_build as $value){
                $edit_data.=$value['name'].':'."\""."\",//".$value['remark'].'\n';
                $test_data.='"'.$value['name'].'"'.':"'.$res[$value['name']].'",';
            }
            $edit_data.='}'.'\n'.']';
            $test_data.='}]';
            $test_chr=strrchr($test_data, ",");
            $test_data=str_replace($test_chr,ltrim($test_chr,','),$test_data);
            $test_data=rtrim($test_data, ",");
            $test_data=addslashes($test_data);
            $edit_chr=strrchr($edit_data, ",");
            $edit_data=str_replace($edit_chr,ltrim($edit_chr,','),$edit_data);
            $edit_data=rtrim($edit_data, ",");
            $edit_data=addslashes($edit_data);
            $edit_data=str_replace('\\\n','\n',$edit_data);
            $json_edit_file = file_get_contents(app()->getAppPath(). 'tem\\' . 'json_edit_tem.txt');
            $json_edit_file = str_replace('{$table_remark}', $table_remark, $json_edit_file);
            $json_edit_file = str_replace('{$url}', $url['edit'], $json_edit_file);
            $json_edit_file = str_replace('{$test_data}', $test_data, $json_edit_file);
            $json_edit_file = str_replace('{$test_api_url}',config('base.test_api_url'), $json_edit_file);
            $json_edit_file = str_replace('{$edit_data}',$edit_data, $json_edit_file);
            file_put_contents(app()->getAppPath() .'json\\'.str_replace('/','_',$url['edit']).'.json', $json_edit_file);
            //get_info
            $arr=[];
            if(!empty($res)){
                foreach ($table_build as $v){
                    $value=[
                        "description"=>$v['remark'],
                        "is_checked"=> 1,
                        "key"=>"data.".$v['name'],
                        "type"=>"Text",
                        "field_type"=>"Object",
                        "value"=>$res[$v['name']]
                    ];
                    array_push($arr,$value);
                }
                foreach ($table_f as $value){
                    $res[$value['all_name']]=Db::name($value['name'])->select()[0];
                    $sql = "select column_name as name,column_comment as remark,data_type as type,is_nullable as is_null ,COLUMN_KEY as ckey from information_schema.columns where table_name='" . config('database.connections.mysql.prefix') . $value['name'] . "' and TABLE_SCHEMA ='" . config('database.connections.mysql.database') . "'";
                    $keys = Db::query($sql);
                    $arr_f=[];
                    foreach ($keys as $v){
                        $value2=[
                            "description"=>$v['remark'],
                            "is_checked"=> 1,
                            "key"=>"data.".$value['all_name'].'.'.$v['name'],
                            "type"=>"Text",
                            "field_type"=>"Object",
                            "value"=>$res[$value['all_name']][$v['name']]
                        ];
                        array_push($arr_f,$value2);
                    }
                    $arr=array_merge($arr,$arr_f);

                }
            }
            $value=$res[$pk];
            $row=addslashes(json_encode($res));
            $param=json_encode($arr);
            $param=str_replace('[','',$param);
            $param=str_replace(']','',$param);
            $json_get_info_file = file_get_contents(app()->getAppPath(). 'tem\\' . 'json_get_info_tem.txt');
            $json_get_info_file = str_replace('{$table_remark}', $table_remark, $json_get_info_file);
            $json_get_info_file = str_replace('{$url}', $url['get_info'], $json_get_info_file);
            $json_get_info_file = str_replace('{$test_api_url}',config('base.test_api_url'), $json_get_info_file);
            $json_get_info_file = str_replace('{$row}',$row, $json_get_info_file);
            $json_get_info_file = str_replace('{$value}',$value, $json_get_info_file);
            $json_get_info_file = str_replace('{$param}',$param, $json_get_info_file);
            file_put_contents(app()->getAppPath() .'json\\'.str_replace('/','_',$url['get_info']).'.json', $json_get_info_file);
            //del
            $json_del_file = file_get_contents(app()->getAppPath(). 'tem\\' . 'json_del_tem.txt');
            $json_del_file = str_replace('{$table_remark}', $table_remark, $json_del_file);
            $json_del_file = str_replace('{$url}', $url['del'], $json_del_file);
            $json_del_file = str_replace('{$test_api_url}',config('base.test_api_url'), $json_del_file);
            file_put_contents(app()->getAppPath() .'json\\'.str_replace('/','_',$url['del']).'.json', $json_del_file);
            echo 'json接口文档生成成功！'.PHP_EOL;
        }else{
            echo '表中缺少数据,json接口文档生成失败!'.PHP_EOL;
        }
        //router
        $txt=[];
        foreach ($url as $key=>$v){
            array_push($txt,"Route::post('".$v."', '".$dian[$key]."');");
        }
        $ex_file=file_get_contents(app()->getRootPath().'route\app.php');
        $file=fopen(app()->getRootPath().'route\app.php',"a+");
        foreach ($txt as $v){
            if(!preg_match('{'.str_replace(')','\)',str_replace('(','\(',$v)).'}',$ex_file)){
                fwrite($file,$v.PHP_EOL);
            }
        }
        fclose($file);
        $output->writeln('生成成功！author:潘霆舒');
    }
}
